<script setup lang="ts">
import {reactive, ref, type Ref} from 'vue'
import {ElNotification, type FormInstance, type FormRules, type ValidateFieldsError} from 'element-plus'
import useValidateErrorDialog from '@/components/dialog/useValidateErrorDialog.ts'
import {updatePassword, type UpdatePasswordRequest} from '@/network/api/user.ts'
import type {InternalRuleItem, Value} from 'async-validator/dist-types/interface'

const isLoading = ref(false)

type UpdatePasswordForm = UpdatePasswordRequest & {
  /**
   * 确认密码
   */
  confirmPassword: string
}

const updatePasswordData: Ref<UpdatePasswordForm> = ref({
  password: '',
  newPassword: '',
  confirmPassword: '',
})

const ruleForm = ref<FormInstance>()

const rules = reactive<FormRules<UpdatePasswordForm>>({
  password: [
    {required: true, message: '旧密码不能为空', trigger: 'blur'},
  ],
  newPassword: [
    {required: true, message: '新密码不能为空', trigger: 'blur'},
  ],
  confirmPassword: [
    {required: true, validator: confirmPasswordValidator, trigger: 'blur'}
  ]
})

function confirmPasswordValidator(rule: InternalRuleItem, value: Value, callback: (error?: string | Error) => void) {
  if (value === '') {
    callback('确认密码不能为空')
  } else if (value !== updatePasswordData.value.newPassword) {
    callback('新密码与确认新密码不一致')
  } else {
    callback()
  }
}

const passwordInput: Ref<HTMLElement | undefined> = ref()
const newPassword: Ref<HTMLElement | undefined> = ref()
const confirmPassword: Ref<HTMLElement | undefined> = ref()

async function updatePasswordClick() {
  isLoading.value = true
  let ruleOk = true
  await ruleForm.value?.validate((isValid: boolean, invalidFields: ValidateFieldsError) => {
    ruleOk = isValid
    if (!isValid) {
      useValidateErrorDialog(invalidFields)
    }
  })
  if (!ruleOk) {
    isLoading.value = false
    return
  }
  updatePassword(updatePasswordData.value).then(res => {
    isLoading.value = false
    if (res.ok) {
      ElNotification({
        title: '修改密码成功',
        message: '修改密码成功',
        type: 'success'
      })
      updatePasswordData.value = {
        password: '',
        newPassword: '',
        confirmPassword: '',
      }
    } else {
      ElNotification({
        title: '修改密码失败',
        message: '未知错误',
        type: 'error'
      })
    }
  }).catch(() => {
    isLoading.value = false
  })
}
</script>

<template>
  <h3>修改密码</h3>
  <el-form
      label-width="auto"
      style="max-width: 300px"
      :rules="rules"
      ref="ruleForm"
      :model="updatePasswordData"
  >
    <el-form-item
        label="旧密码"
        prop="password"
    >
      <el-input
          v-model="updatePasswordData.password"
          placeholder="请输入旧密码"
          type="password"
          show-password
          ref="passwordInput"
          autofocus
          @keyup.enter="newPassword?.focus()"
      />
    </el-form-item>
    <el-form-item
        label="新密码"
        prop="newPassword"
    >
      <el-input
          v-model="updatePasswordData.newPassword"
          placeholder="请输入新密码"
          type="password"
          ref="newPassword"
          show-password
          @keyup.enter="confirmPassword?.focus()"
      />
    </el-form-item>
    <el-form-item
        label="确认密码"
        prop="confirmPassword"
    >
      <el-input
          v-model="updatePasswordData.confirmPassword"
          placeholder="请输入确认密码"
          type="password"
          ref="confirmPassword"
          show-password
          @keyup.enter="updatePasswordClick"
      />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="updatePasswordClick" :loading="isLoading">
        {{ isLoading ? '正在修改' : '修改密码' }}
      </el-button>
    </el-form-item>
  </el-form>
</template>
